#!/usr/bin/python3
# -*- coding: utf-8 -*-
# coding=utf-8
# Author: BillySir
from __future__ import print_function
from typing import *
from chess_board import *


class T2D:
    """2维与1维的变换"""

    board: ChessBoard = None    # 棋盘
    width: int = None       # 2维宽度
    height: int = None      # 2维高度
    outside_cell: Cell = None   # 棋盘范围外统一用此cell值表示

    @staticmethod
    def to_xy(index: int) -> (int, int):
        """1维坐标转2维"""
        x = index % T2D.width
        y = index // T2D.width
        return x, y

    @staticmethod
    def to_index(x: int, y: int) -> int:
        """2维坐标转1维"""
        return y * T2D.width + x

    @staticmethod
    def near4(cell: Cell) -> List[Cell]:
        """相邻4格。即上、下、左、右共4格"""
        index = cell.index
        x, y = T2D.to_xy(index)
        return [T2D.get_cell(x, y - 1),
                T2D.get_cell(x - 1, y), T2D.get_cell(x + 1, y),
                T2D.get_cell(x, y + 1)]

    @staticmethod
    def near8(cell: Cell) -> List[Cell]:
        """相邻的8格"""
        index = cell.index
        x, y = T2D.to_xy(index)
        return [T2D.get_cell(x - 1, y - 1), T2D.get_cell(x, y - 1), T2D.get_cell(x + 1, y - 1),
                T2D.get_cell(x - 1, y), T2D.get_cell(x + 1, y),
                T2D.get_cell(x - 1, y + 1), T2D.get_cell(x, y + 1), T2D.get_cell(x + 1, y + 1)]

    @staticmethod
    def near4corner(cell: Cell) -> List[Cell]:
        """相邻4角。即左上、右上、左下、右下共4格"""
        index = cell.index
        x, y = T2D.to_xy(index)
        return [T2D.get_cell(x - 1, y - 1), T2D.get_cell(x + 1, y - 1),
                T2D.get_cell(x - 1, y + 1), T2D.get_cell(x + 1, y + 1)]

    @staticmethod
    def ew(cell: Cell) -> List[Cell]:
        """相邻左、右2格"""
        index = cell.index
        x, y = T2D.to_xy(index)
        return [T2D.get_cell(x - 1, y), T2D.get_cell(x + 1, y)]

    @staticmethod
    def sn(cell: Cell) -> List[Cell]:
        """相邻下、上2格"""
        index = cell.index
        x, y = T2D.to_xy(index)
        return [T2D.get_cell(x, y - 1),
                T2D.get_cell(x, y + 1)]

    @staticmethod
    def get_cell(x: int, y: int) -> Cell:
        """获取指定坐标的格"""
        line_count = T2D.get_line_count()

        if x < 0 or x >= T2D.width:
            return T2D.outside_cell
        if y < 0 or y >= line_count:
            return T2D.outside_cell
        index = T2D.to_index(x, y)
        return T2D.board.cells[index]

    @staticmethod
    def get_line_count():
        """获取棋盘高度"""
        if T2D.height is None:
            assert T2D.board is not None, "T2D.board can not be None"
            assert T2D.width is not None, "T2D.line_len can not be None"
            assert len(T2D.board.cells) % T2D.width == 0, "len(T2D.board.cells) must times of T2D.line_len"
            T2D.height = len(T2D.board.cells) / T2D.width
        return int(T2D.height)

    @classmethod
    def set_child(cls, get_child_position):
        """通过2维坐标批量设置cell的child"""
        line_count = T2D.get_line_count()
        for y in range(line_count):
            for x in range(T2D.width):
                cell_parent = T2D.get_cell(x, y)
                x1, y1 = get_child_position(x, y)
                if 0 <= x1 < T2D.width and 0 <= y1 < line_count:
                    cell_child = T2D.get_cell(x1, y1)
                    cell_child.bind_parents([cell_parent])

    @classmethod
    def get_cells_list(cls, pattern):
        """按指定的方式获取cell集合的集合
pattern:
  - 每一行
  | 每一列
  / 对角斜线，暂只支持正方形棋盘
  \\ 对解反斜线，暂只支持正方形棋盘
  // 每一斜线
  \\\\ 每一反斜线，注意按语法每1个\\可能要用2个\\表示"""
        cells_list = []
        if T2D.board is None:
            return cells_list
        cells = T2D.board.cells
        width = T2D.width
        height = T2D.height

        if isinstance(pattern, Tuple):
            w, h = pattern
            if width % w != 0:
                raise Exception("width not times of w. width:%d, w:%d" % (width, w))
            if height % h != 0:
                raise Exception("height not times of h. height:%d, h:%d" % (height, h))
            cells_list = [
                [
                    cells[y1 * width * (height // h) + x1 * (width // w) + y2 * width + x2]
                    for y2 in range(h) for x2 in range(w)
                ] for y1 in range(height // h) for x1 in range(width // w)
            ]
            return cells_list
        # 切分出单字符与双字符
        pattern = pattern.replace("", ",")
        pattern = pattern.replace("/,/", "//")
        pattern = pattern.replace("\\,\\", "\\\\")

        for p in pattern.strip(",").split(","):
            if p == "-":
                cells_list.extend([cells[i * width:(i + 1) * width] for i in range(height)])
            elif p == "|":
                cells_list.extend([cells[i: (width * height): height] for i in range(width)])
            elif p == "/":
                if width != height:
                    raise Exception("width must equals height. width:%d, height:%d" % (width, height))
                cells_list.append(cells[width - 1: width * height - 1: width - 1])
            elif p == "//":
                if width != height:
                    raise Exception("width must equals height. width:%d, height:%d" % (width, height))
                for w in range(width):
                    cells_list.append(cells[w: width * w + 1: width - 1])
                for h in range(1, height):
                    cells_list.append(cells[width * (h + 1) - 1: width * height - (height - h - 1): width - 1])
            elif p == "\\":
                if width != height:
                    raise Exception("width must equals height. width:%d, height:%d" % (width, height))
                cells_list.append(cells[0: width * height: width + 1])
            elif p == "\\\\":
                if width != height:
                    raise Exception("width must equals height. width:%d, height:%d" % (width, height))
                for w in range(width):
                    cells_list.append(cells[width * (height - 1 - w): width * (height - 1) + w + 1: width + 1])
                for h in range(1, height):
                    cells_list.append(cells[h: width * (height - h): width + 1])
                pass
            else:
                raise Exception("invalid pattern:" + p)
        return cells_list
